home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / gnustuff / tos / bash / bash-108 / bash-108.zoo / src / nojobs.c.orig < prev    next >
Encoding:
Text File  |  1991-09-12  |  8.0 KB  |  361 lines

  1. /* The thing that makes children, remembers them, and contains wait loops. */
  2.  
  3. /* This file works under BSD, System V, minix, and Posix systems. */
  4.  
  5. /* Copyright (C) 1987,1989 Free Software Foundation, Inc.
  6.  
  7. This file is part of GNU Bash, the Bourne Again SHell.
  8.  
  9. Bash is free software; you can redistribute it and/or modify it under
  10. the terms of the GNU General Public License as published by the Free
  11. Software Foundation; either version 1, or (at your option) any later
  12. version.
  13.  
  14. Bash is distributed in the hope that it will be useful, but WITHOUT ANY
  15. WARRANTY; without even the implied warranty of MERCHANTABILITY or
  16. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  17. for more details.
  18.  
  19. You should have received a copy of the GNU General Public License along
  20. with Bash; see the file COPYING.  If not, write to the Free Software
  21. Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
  22.  
  23. #include <stdio.h>
  24. #include <sys/types.h>
  25. #include <fcntl.h>
  26. #include <signal.h>
  27. #include <setjmp.h>
  28. #include <errno.h>
  29.  
  30. #include "config.h"
  31. #include "general.h"
  32. #include "jobs.h"
  33.  
  34. #if !defined (USG) && !defined (_POSIX_VERSION)
  35. #  include <sgtty.h>
  36. #else
  37. #  if defined (USG)
  38. #    include <termio.h>
  39. #    include <sys/ttold.h>
  40. #  else 
  41. #    include <termios.h>
  42. #  endif
  43. #endif /* !USG && !_POSIX_VERSION */
  44.  
  45. #ifndef SIGABRT
  46. #define SIGABRT SIGIOT
  47. #endif
  48.  
  49. #if defined (USG) || defined (_POSIX_VERSION)
  50. #define killpg(pg, sig)        kill(-(pg),(sig))
  51. #endif
  52.  
  53. #if defined (USG)
  54. #define siginterrupt(sig, code)
  55. #endif
  56.  
  57. pid_t last_made_pid = (pid_t)-1;
  58. pid_t last_asynchronous_pid = (pid_t)-1;
  59.  
  60. extern int errno;
  61.  
  62. /* Initialize the job control mechanism, and set up the tty stuff. */
  63. initialize_jobs ()
  64. {
  65.   get_tty_state ();
  66. }
  67.  
  68. /* Setup this shell to handle C-C, etc. */
  69. initialize_job_signals ()
  70. {
  71.   extern int login_shell;
  72.   extern sighandler sigint_sighandler ();
  73.  
  74.   signal (SIGINT, sigint_sighandler);
  75.   signal (SIGQUIT, SIG_IGN);
  76.  
  77.   /* If this is a login shell we don't wish to be disturbed by
  78.      stop signals. */
  79.   if (login_shell)
  80.     {
  81. #ifdef SIGTSTP
  82.       signal (SIGTSTP, SIG_IGN);
  83.       signal (SIGTTOU, SIG_IGN);
  84.       signal (SIGTTIN, SIG_IGN);
  85. #endif
  86.     }
  87. }
  88.  
  89. /* Fork, handling errors.  Returns the pid of the newly made child, or 0.
  90.    COMMAND is just for remembering the name of the command; we don't do
  91.    anything else with it.  ASYNC_P says what to do with the tty.  If
  92.    non-zero, then don't give it away. */
  93. pid_t
  94. make_child (command, async_p)
  95.      char *command;
  96.      int async_p;
  97. {
  98.   pid_t pid;
  99.  
  100.   /* Discard saved memory. */
  101.   if (command)  
  102.     free (command);
  103.  
  104.   /* Make new environment array if neccessary. */
  105.   maybe_make_export_env ();
  106.  
  107.   /* Create the child, handle severe errors. */
  108.   if ((pid = fork ()) < 0)
  109.     {
  110.       report_error ("fork: %s", strerror (errno));
  111.  
  112.       throw_to_top_level ();
  113.     }
  114.  
  115.   if (!pid)
  116.     {
  117.       /* Ignore INT and QUIT in asynchronous children. */
  118.       if (async_p)
  119.     {
  120.       signal (SIGINT, SIG_IGN);
  121.       signal (SIGQUIT, SIG_IGN);
  122.       last_asynchronous_pid = getpid ();
  123.     }
  124.       else
  125.     {
  126.       restore_default_signal (SIGINT);
  127.       restore_default_signal (SIGQUIT);
  128.  
  129. #if defined (SIGTSTP)
  130.       signal (SIGTSTP, SIG_DFL);
  131.       signal (SIGTTIN, SIG_DFL);
  132.       signal (SIGTTOU, SIG_DFL);
  133. #endif
  134.  
  135.       restore_original_signals ();     /* cancel traps, in trap.c */
  136.     }
  137.  
  138.       /* Children are easily terminated with SIGTERM. */
  139.       restore_default_signal (SIGTERM);
  140.     }
  141.   else
  142.     {
  143.       /*
  144.        * In the parent.
  145.        */
  146.       last_made_pid = pid;
  147.  
  148.       if (async_p)
  149.     last_asynchronous_pid = pid;
  150.     }
  151.   return (pid);
  152. }
  153.  
  154. /* Wait for a single pid (PID) and return its exit status. */
  155.  
  156. wait_for_single_pid (pid)
  157.      pid_t pid;
  158. {
  159.   pid_t got_pid;
  160.   WAIT status;
  161.  
  162.   siginterrupt (SIGINT, 1);
  163.   while ((got_pid = wait (&status)) != pid)
  164.     {
  165.       if (got_pid < 0)
  166.     {
  167.       if (errno != EINTR && errno != ECHILD)
  168.         {
  169.           siginterrupt (SIGINT, 0);
  170.           file_error ("wait");
  171.         }
  172.       break;
  173.     }
  174.     }
  175.   siginterrupt (SIGINT, 0);
  176.   QUIT;
  177. }
  178.  
  179. /* Wait for all of the shell's children to exit. */
  180.  
  181. wait_for_background_pids ()
  182. {
  183.   /* If we aren't using job control, we let the kernel take care of the
  184.      bookkeeping for us.  wait () will return -1 and set errno to ECHILD 
  185.      when there are no more unwaited-for child processes on both
  186.      4.2 BSD-based and System V-based systems. */
  187.  
  188.   siginterrupt (SIGINT, 1);
  189.   while (1)
  190.     {
  191.       pid_t got_pid;
  192.       WAIT status;
  193.  
  194.       while ((got_pid = wait(&status)) != -1)  /* wait for ECHILD */
  195.     ;
  196.       if (errno != EINTR && errno != ECHILD)
  197.     {
  198.       siginterrupt (SIGINT, 0);
  199.       file_error("wait");
  200.     }
  201.       break;
  202.     }
  203.   siginterrupt (SIGINT, 0);
  204.   QUIT;
  205. }
  206.  
  207. /* Wait for pid (one of our children) to terminate. */
  208. int
  209. wait_for (pid)
  210.      pid_t pid;
  211. {
  212.   extern int interactive;
  213.   int return_val;
  214.   pid_t got_pid;
  215.   WAIT status;
  216.  
  217.   /* Make sure that the process we are waiting for is valid. */
  218.   if ((kill (pid, 0) < 0) && (errno == ESRCH))
  219.     return (0);
  220.  
  221.   siginterrupt (SIGINT, 1);
  222.   while ((got_pid = wait (&status)) != pid)
  223.     {
  224.       if (got_pid < 0 && errno == ECHILD)
  225.     {
  226. #if !defined (_POSIX_VERSION)
  227.       status.w_termsig = status.w_retcode = 0;
  228. #else
  229.       status = 0;
  230. #endif /* _POSIX_VERSION */
  231.       break;
  232.     }
  233.       else if (got_pid < 0 && errno != EINTR)
  234.     programming_error ("got errno %d while waiting for %d", errno, pid);
  235.     }
  236.   siginterrupt (SIGINT, 0);
  237.  
  238. #if 0
  239.   /* Not needed because the builtin wait does not go through this path. */
  240.   if (interactive)    /* allow the user to ^C out of the builtin wait */
  241.     QUIT;
  242. #endif
  243.  
  244.   /* Default return value. */
  245.   /* ``a full 8 bits of status is returned'' */
  246.   if (WIFSIGNALED (status))
  247.     return_val = 128 + WTERMSIG (status);
  248.   else
  249.     return_val = WEXITSTATUS (status);
  250.                             
  251.   if (!WIFSTOPPED (status) && WIFSIGNALED (status) &&
  252.       (WTERMSIG (status) != SIGINT))
  253.     {
  254.       extern char *sys_siglist[];
  255.       fprintf (stderr, "%s", sys_siglist[WTERMSIG (status)]);
  256.       if (WIFCORED (status))
  257.     fprintf (stderr, " (core dumped)");
  258.       fprintf (stderr, "\n");
  259.     }
  260.  
  261.   if (WIFSIGNALED (status) || WIFSTOPPED (status))
  262.     set_tty_state ();
  263.   else
  264.     get_tty_state ();
  265.                             
  266.   return (return_val);
  267. }
  268.  
  269. /* Give PID SIGNAL.  This determines what job the pid belongs to (if any).
  270.    If PID does belong to a job, and the job is stopped, then CONTinue the
  271.    job after giving it SIGNAL.  Returns -1 on failure.  If GROUP is non-null,
  272.    then kill the process group associated with PID. */
  273. int
  274. kill_pid (pid, signal, group)
  275.      pid_t pid;
  276.      int signal, group;
  277. {
  278.   int result;
  279.  
  280.   if (group)
  281.     result = killpg (pid, signal);
  282.   else
  283.     result = kill (pid, signal);
  284.  
  285.   return (result);
  286. }
  287.  
  288. #if defined (_POSIX_VERSION)
  289. static struct termios shell_tty_info;
  290. #else
  291. #  if defined (USG)
  292. static struct termio shell_tty_info;
  293. #  else
  294. static struct sgttyb shell_tty_info;
  295. #  endif /* USG */
  296. #endif /* _POSIX_VERSION */
  297.  
  298. static int got_tty_state = 0;
  299.  
  300. /* Fill the contents of shell_tty_info with the current tty info. */
  301. get_tty_state ()
  302. {
  303.   int tty = open ("/dev/tty", O_RDONLY);
  304.   if (tty != -1)
  305.     {
  306.    
  307. #if defined (_POSIX_VERSION)
  308.       tcgetattr (tty, &shell_tty_info);
  309. #else
  310. #  if defined (USG)
  311.       ioctl (tty, TCGETA, &shell_tty_info);
  312. #  else
  313.       ioctl (tty, TIOCGETP, &shell_tty_info);
  314. #  endif
  315. #endif
  316.       close (tty);
  317.       got_tty_state = 1;
  318.     }
  319. }
  320.  
  321. /* Make the current tty use the state in shell_tty_info. */
  322. set_tty_state ()
  323. {
  324.   int tty = open ("/dev/tty", O_RDONLY);
  325.   if (tty != -1)
  326.     {
  327.       if (!got_tty_state)
  328.         return;
  329. #if defined (_POSIX_VERSION)
  330.       tcsetattr (tty, TCSADRAIN, &shell_tty_info);
  331. #else
  332. #  if defined (USG)
  333.       ioctl (tty, TCSETAW, &shell_tty_info);  /* Wait for output, no flush */
  334. #  else
  335.       ioctl (tty, TIOCSETN, &shell_tty_info);
  336. #  endif
  337. #endif
  338.       close (tty);
  339.     }
  340. }
  341.  
  342. /* Give the terminal to PGRP.  */
  343. give_terminal_to (pgrp)
  344.      pid_t pgrp;
  345. {
  346. }
  347.  
  348. /* Stop a pipeline. */
  349. stop_pipeline (async, ignore)
  350.      int async;
  351.      char *ignore;
  352. {
  353. }
  354.  
  355. /* Print descriptive information about the job with leader pid PID. */
  356. describe_pid (pid)
  357.      pid_t pid;
  358. {
  359.   fprintf (stderr, "<%d>\n", (int) pid);
  360. }
  361.